科技
3 分钟,纯 CSS 实现一个 tabs 组件
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的
offer
。 已帮助数百位同学拿到了中大厂offer
Hello,大家好,我是 Sunday。
tabs
组件是在日常开发中的常见组件,很多同学表示:组件库的 tabs
不好看,自己实现又不知道怎么去做。
所以说,今天,咱们就花上几分钟的时间,通过纯 css
的方式来实现一个 tabs
组件,以帮助大家完成自定义 tabs
组件的逻辑。
html 部分
先上代码:
<div class="container">
<div class="tabs">
<input type="radio" id="radio-1" name="tabs" checked="" />
<label class="tab" for="radio-1">
首页
<span class="notification">2</span>
</label>
<input type="radio" id="radio-2" name="tabs" />
<label class="tab" for="radio-2">分类</label>
<input type="radio" id="radio-3" name="tabs" />
<label class="tab" for="radio-3">我的</label>
<span class="glider"></span>
</div>
</div>
这里需要 注意:在 html 部分需要设计成 input + label
的形式,而不能使用 div
的方案。
核心原因有两点:
input[type='radio']
元素天生就具有 互斥性,即只能选中一个。这使得在实现多选一的标签页功能时非常简便和自然,无需手动管理状态。当选择某个标签页时,其对应的 radio 按钮会被选中,而 CSS 可以通过 :checked 伪类来捕捉这一状态的变化,从而触发样式变化,比如滑块的移动、文本颜色的变化等。
整个 HTML 结构设计逻辑如下:
container
:最外层容器,用于包裹整个标签页组件。tabs
:用于包含标签页的所有内容,包括input
、label
和glider
滑块。input[type='radio']
:作为标签页的控制器,决定哪个标签页被选中。每个标签页对应一个radio
按钮,三个input
元素的id
和label
元素的for
属性配对,使得点击label
可以选择对应的radio
按钮。label.tab
:每个标签页的实际显示部分,包括文字和可选的通知标记notification
。glider
:滑块,用于在标签页切换时移动,表示当前选择的标签页。
CSS样式
body {
padding: 300px;
}
.tabs {
width: 152px;
display: flex;
position: relative;
background-color: #fff;
box-shadow: 0 0 1px 0 rgba(24, 94, 224, 0.15), 0 6px 12px 0 rgba(24, 94, 224, 0.15);
padding: 12px;
border-radius: 99px;
}
body
:在body
中添加了padding
,使页面内容离顶部和边界有一定的距离,便于演示。tabs
:设置了tabs
容器的宽度(152px),使用flex
布局,子元素排列在一行。容器具有一定的阴影效果和圆角,使其更具层次感。
.tabs * {
z-index: 2;
}
将 tabs
内部的所有元素的z-index
设置为2,确保这些元素位于滑块(glider
)之上。
.container input[type='radio'] {
display: none;
}
隐藏 radio
按钮,只保留它们的功能,不显示在页面上。
.tab {
display: flex;
align-items: center;
justify-content: center;
height: 30px;
width: 50px;
font-size: 14px;
color: black;
font-weight: 500;
border-radius: 99px;
cursor: pointer;
transition: color 0.15s ease-in;
}
每个标签页 label.tab
设置了固定的大小,字体样式和颜色。使用flex
布局使文本居中,边角圆滑,鼠标悬停时呈现为点击手势。使用transition
实现颜色过渡效果。
.notification {
display: flex;
align-items: center;
justify-content: center;
width: 14px;
height: 14px;
position: absolute;
top: 10px;
left: 30%;
font-size: 10px;
margin-left: 10px;
border-radius: 50%;
background-color: #e6eef9;
transition: 0.15s ease-in;
}
notification
是标签页上的小圆点,用于显示通知数量。设置了大小、位置、字体大小和颜色。transition
使背景色和位置的变化更为平滑。
.container input[type='radio']:checked + label {
color: #185ee0;
}
.container input[type='radio']:checked + label > .notification {
background-color: #185ee0;
color: #fff;
margin: 0px;
}
当 radio
按钮被选中时,相应的label
颜色变为蓝色,通知标记的背景色和文本颜色也会改变。
.container input[id='radio-1']:checked ~ .glider {
transform: translateX(0);
}
.container input[id='radio-2']:checked ~ .glider {
transform: translateX(100%);
}
.container input[id='radio-3']:checked ~ .glider {
transform: translateX(200%);
}
通过 CSS
选择器,当某个radio
按钮被选中时,glider
滑块将根据不同的radio
按钮移动相应的距离,translateX
是基于父容器的宽度(这里是152px)。
.glider {
position: absolute;
display: flex;
height: 30px;
width: 50px;
background-color: #e6eef9;
z-index: 1;
border-radius: 99px;
transition: 0.25s ease-out;
}
glider
的样式定义了滑块的大小、位置和颜色,设置为absolute
以便在容器内自由移动,transition
使其移动平滑。
1v1私教,帮大家拿到满意的 offer
我目前在做一个 前端训练营 ,主打的就是:1v1 私教,帮大家拿到满意的 offer
。
也可以直接加我微信沟通,备注【训练营】: